/**
 * User: tsegelskyi
 * Date: 25.02.13
 * Time: 16:30
 */

import org.junit.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertTrue;


public class PointTest {
    Point origin;

    @Before
    public void setUp() throws Exception {
        origin = new Point(0, 0);
    }

    @Test
    public void test3() {
        Point p = new Point(8, 3);
        Point q = new Point(8, 2);
        Point r = new Point(9, 1);
        assertEquals(1, p.SLOPE_ORDER.compare(q, r));
    }

    @Test(expected = NullPointerException.class)
    public void testSlopeToWithNull() {
        Point p1 = new Point(0, 0);
        p1.slopeTo(null);
    }

    @Test(expected = NullPointerException.class)
    public void testCompareToWithNullPoint() {
        Point p1 = new Point(0, 0);
        p1.compareTo(null);

    }

    @Test(expected = NullPointerException.class)
    public void testCompareTwoWithBothNull() {
        Point p1 = new Point(0, 0);
        p1.SLOPE_ORDER.compare(null, null);

    }


    @Test(expected = NullPointerException.class)
    public void testCompareTwoWithOneNull() {
        Point p1 = new Point(0, 0);
        p1.SLOPE_ORDER.compare(null, new Point(0, 0));

    }

    @Test
    public void testCompareIsLessThan() {
        Point p1 = new Point(0, 0);
        Point p2 = new Point(1, 1);
        assertEquals(-1, p1.compareTo(p2));
    }

    @Test
    public void testComparIsLessThanWhenYEquals() {
        Point p1 = new Point(0, 0);
        Point p2 = new Point(1, 0);
        assertEquals(-1, p1.compareTo(p2));
    }

    @Test
    public void testCompareEquals() {
        Point p1 = new Point(1, 1);
        Point p2 = new Point(1, 1);
        assertEquals(0, p1.compareTo(p2));
    }

    @Test
    public void testCompareGreaterThan() {
        Point p1 = new Point(5, 5);
        Point p2 = new Point(1, 1);
        assertEquals(1, p1.compareTo(p2));
    }

    @Test
    public void testCompareGreaterThanWhenYEquals() {
        Point p1 = new Point(5, 1);
        Point p2 = new Point(1, 1);
        assertEquals(1, p1.compareTo(p2));
    }

    @Test
    public void testSlopeToWhenYAreDifferent() {
        Point p1 = new Point(5, 1);
        Point p2 = new Point(1, 2);
        assertEquals(-1d / 4d, p1.slopeTo(p2), 0.01);
    }


    @Test
    public void testSlopeToVerticalFromTest1() {
        Point p = new Point(13, 264);
        Point q = new Point(13, 179);
        assertEquals(Double.POSITIVE_INFINITY, p.slopeTo(q), 0.01);
    }

    @Test
    public void testSlopeToHorizontalFromTest1() {
        Point p = new Point(132, 13);
        Point q = new Point(133, 13);
        assertEquals(0, p.slopeTo(q), 0.01);
    }


    @Test
    public void testSlopeToHorizontal() {
        Point p1 = new Point(5, 1);
        Point p2 = new Point(1, 1);
        assertEquals(0d, p1.slopeTo(p2), 0.01);
    }

    @Test
    public void testSlopeToVertical() {
        Point p1 = new Point(1, 1);
        Point p2 = new Point(1, 5);
        assertEquals(Double.POSITIVE_INFINITY, p1.slopeTo(p2), 0.01);
    }

    @Test
    public void testSlopeToDegenerate() {
        Point p1 = new Point(1, 1);
        Point p2 = new Point(1, 1);
        assertEquals(Double.NEGATIVE_INFINITY, p1.slopeTo(p2), 0.01);
    }

    @Test
    public void testSlopeOrderDifferentY() {
        List<Point> points = new ArrayList<Point>();
        points.add(new Point(1, 2));
        points.add(new Point(2, 3));
        points.add(new Point(5, 10));
        points.add(new Point(4, 0));
        points.add(new Point(3, 1));

        Collections.sort(points, origin.SLOPE_ORDER);
        System.out.println("========Diff Y========");

        for (int i = 1; i < points.size(); i++) {
            System.out.println(points.get(i - 1) + ":" + origin.slopeTo(points.get(i - 1)) + " < " + points.get(i) + ":" + origin.slopeTo(points.get(i)));
            assertTrue(origin.slopeTo(points.get(i - 1)) <= origin.slopeTo(points.get(i)));
        }
    }



    @Test
    public void testSlopeOrderHorizontal() {
        List<Point> points = new ArrayList<Point>();
        points.add(new Point(0, 1));
        points.add(new Point(0, 1));
        points.add(new Point(0, 1));

        Collections.sort(points, origin.SLOPE_ORDER);
        System.out.println("========Horiz========");

        for (int i = 1; i < points.size(); i++) {
            System.out.println(points.get(i - 1) + ":" + origin.slopeTo(points.get(i - 1)) + " < " + points.get(i) + ":" + origin.slopeTo(points.get(i)));
            assertTrue(origin.slopeTo(points.get(i - 1)) <= origin.slopeTo(points.get(i)));
        }
    }

    @Test
    public void testSlopeOrderVertical() {
        List<Point> points = new ArrayList<Point>();
        points.add(new Point(1, 0));
        points.add(new Point(1, 0));
        points.add(new Point(1, 0));

        Collections.sort(points, origin.SLOPE_ORDER);
        System.out.println("========Vert========");

        for (int i = 1; i < points.size(); i++) {
            System.out.println(points.get(i - 1) + ":" + origin.slopeTo(points.get(i - 1)) + " < " + points.get(i) + ":" + origin.slopeTo(points.get(i)));
            assertTrue(origin.slopeTo(points.get(i - 1)) <= origin.slopeTo(points.get(i)));
        }
    }

    @Test
    public void testSlopeOrderDegenerate() {
        List<Point> points = new ArrayList<Point>();
        points.add(new Point(1, 1));
        points.add(new Point(10, 10));
        points.add(new Point(0, 0));

        Collections.sort(points, origin.SLOPE_ORDER);
        System.out.println("========Degenerate========");

        for (int i = 1; i < points.size(); i++) {
            System.out.println(points.get(i - 1) + ":" + origin.slopeTo(points.get(i - 1)) + " < " + points.get(i) + ":" + origin.slopeTo(points.get(i)));
            assertTrue(origin.slopeTo(points.get(i - 1)) <= origin.slopeTo(points.get(i)));
        }
    }


    @Test
    public void testSlopeOrderMixed() {
        List<Point> points = new ArrayList<Point>();
        points.add(new Point(1, 2));
        points.add(new Point(2, 3));
        points.add(new Point(5, 10));
        points.add(new Point(4, 0));
        points.add(new Point(3, 0));
        points.add(new Point(0, 0));
        points.add(new Point(4, 0));
        points.add(new Point(0, 1));


        Collections.sort(points, origin.SLOPE_ORDER);
        System.out.println("========Diff Y========");

        for (int i = 1; i < points.size(); i++) {
            System.out.println(points.get(i - 1) + ":" + origin.slopeTo(points.get(i - 1)) + " < " + points.get(i) + ":" + origin.slopeTo(points.get(i)));
            assertTrue(origin.slopeTo(points.get(i - 1)) <= origin.slopeTo(points.get(i)));
        }
    }
}
